package code.gui;

import code.Aresta;
import code.Grafo;
import code.Controlador;
import code.No;
import code.NoEstado;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

public class FrmInterface extends javax.swing.JFrame {

    private final DefaultListModel modelGrafo = new DefaultListModel();
    private final DefaultListModel modelNo = new DefaultListModel();
    private final DefaultListModel modelAresta = new DefaultListModel();
    private final DefaultComboBoxModel modelCbNoA = new DefaultComboBoxModel();
    private final DefaultComboBoxModel modelCbNoB = new DefaultComboBoxModel();
    private final Controlador controlador;

    public FrmInterface() {
        initComponents();

        //Inicializa os JLists
        listGrafo.setModel(modelGrafo);
        listNo.setModel(modelNo);
        listAresta.setModel(modelAresta);
        cbNoA.setModel(modelCbNoA);
        cbNoB.setModel(modelCbNoB);

        controlador = Controlador.getInstance();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        lbNomeDoGrafo = new javax.swing.JLabel();
        scrollPaneGrafo = new javax.swing.JScrollPane();
        listGrafo = new javax.swing.JList(new DefaultListModel());
        btAdicionarGrafo = new javax.swing.JButton();
        btAlterarGrafo = new javax.swing.JButton();
        btRemoverGrafo = new javax.swing.JButton();
        tfNomeGrafo = new javax.swing.JTextField();
        lbNomeDoNo = new javax.swing.JLabel();
        separator1 = new javax.swing.JSeparator();
        tfNomeNo = new javax.swing.JTextField();
        lbCustoDoNo = new javax.swing.JLabel();
        tfCustoNo = new javax.swing.JTextField();
        scrollPaneNo = new javax.swing.JScrollPane();
        listNo = new javax.swing.JList();
        btAdicionarNo = new javax.swing.JButton();
        btAlterarNo = new javax.swing.JButton();
        btRemoverNo = new javax.swing.JButton();
        separator2 = new javax.swing.JSeparator();
        lbNomeDaAresta = new javax.swing.JLabel();
        tfNomeAresta = new javax.swing.JTextField();
        lbCustoAresta = new javax.swing.JLabel();
        scrollPaneAresta = new javax.swing.JScrollPane();
        listAresta = new javax.swing.JList();
        tfCustoAresta = new javax.swing.JTextField();
        btAdicionarAresta = new javax.swing.JButton();
        btAlterarAresta = new javax.swing.JButton();
        btRemoverAresta = new javax.swing.JButton();
        lbNoA = new javax.swing.JLabel();
        cbNoA = new javax.swing.JComboBox();
        lbNoB = new javax.swing.JLabel();
        cbNoB = new javax.swing.JComboBox();
        lbEstadoNo = new javax.swing.JLabel();
        cbEstadoNo = new javax.swing.JComboBox();
        btAbrir = new javax.swing.JButton();
        btSalvar = new javax.swing.JButton();
        btVisualizarNo = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Exercicío 1");
        setResizable(false);

        lbNomeDoGrafo.setText("Nome do Grafo:");

        listGrafo.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        listGrafo.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                listGrafoMouseClicked(evt);
            }
        });
        listGrafo.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                listGrafoValueChanged(evt);
            }
        });
        scrollPaneGrafo.setViewportView(listGrafo);

        btAdicionarGrafo.setText("Adicionar");
        btAdicionarGrafo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAdicionarGrafoActionPerformed(evt);
            }
        });

        btAlterarGrafo.setText("Alterar");
        btAlterarGrafo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAlterarGrafoActionPerformed(evt);
            }
        });

        btRemoverGrafo.setText("Remover");
        btRemoverGrafo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btRemoverGrafoActionPerformed(evt);
            }
        });

        lbNomeDoNo.setText("Nome do Nó:");

        lbCustoDoNo.setText("Custo do Nó:");

        listNo.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        listNo.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                listNoMouseClicked(evt);
            }
        });
        listNo.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                listNoValueChanged(evt);
            }
        });
        scrollPaneNo.setViewportView(listNo);

        btAdicionarNo.setText("Adicionar");
        btAdicionarNo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAdicionarNoActionPerformed(evt);
            }
        });

        btAlterarNo.setText("Alterar");
        btAlterarNo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAlterarNoActionPerformed(evt);
            }
        });

        btRemoverNo.setText("Remover");
        btRemoverNo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btRemoverNoActionPerformed(evt);
            }
        });

        lbNomeDaAresta.setText("Nome da Aresta:");

        lbCustoAresta.setText("Custo da Aresta:");

        listAresta.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        listAresta.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                listArestaMouseClicked(evt);
            }
        });
        scrollPaneAresta.setViewportView(listAresta);

        btAdicionarAresta.setText("Adicionar");
        btAdicionarAresta.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAdicionarArestaActionPerformed(evt);
            }
        });

        btAlterarAresta.setText("Alterar");
        btAlterarAresta.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAlterarArestaActionPerformed(evt);
            }
        });

        btRemoverAresta.setText("Remover");
        btRemoverAresta.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btRemoverArestaActionPerformed(evt);
            }
        });

        lbNoA.setText("Nó A:");

        lbNoB.setText("Nó B:");

        lbEstadoNo.setText("Estado:");

        cbEstadoNo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Inicial", "Intermediário", "Final" }));

        btAbrir.setText("Abrir");
        btAbrir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAbrirActionPerformed(evt);
            }
        });

        btSalvar.setText("Salvar");
        btSalvar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btSalvarActionPerformed(evt);
            }
        });

        btVisualizarNo.setText("Visualizar");
        btVisualizarNo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btVisualizarNoActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(separator1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 598, Short.MAX_VALUE)
                        .addContainerGap())
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                .add(lbNomeDoGrafo)
                                .add(8, 8, 8)
                                .add(tfNomeGrafo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 124, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 211, Short.MAX_VALUE)
                                .add(btSalvar)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                .add(btAbrir))
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                .add(scrollPaneGrafo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 452, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                    .add(btRemoverGrafo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)
                                    .add(btAlterarGrafo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)
                                    .add(btAdicionarGrafo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)
                                    .add(btVisualizarNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 137, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
                        .add(20, 20, 20))
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(separator2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 598, Short.MAX_VALUE)
                            .add(layout.createSequentialGroup()
                                .add(scrollPaneNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 452, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(btAdicionarNo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 135, Short.MAX_VALUE)
                                    .add(btAlterarNo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 135, Short.MAX_VALUE)
                                    .add(btRemoverNo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 135, Short.MAX_VALUE)))
                            .add(layout.createSequentialGroup()
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(layout.createSequentialGroup()
                                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                                .add(lbNoA)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                                .add(cbNoA, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 135, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                .add(lbNoB))
                                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                                .add(lbNomeDaAresta)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                                .add(tfNomeAresta, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 124, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(layout.createSequentialGroup()
                                                .add(lbCustoAresta)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                                .add(tfCustoAresta, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 47, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                            .add(cbNoB, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 135, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                                    .add(scrollPaneAresta, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 452, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(btAdicionarAresta, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE)
                                    .add(btAlterarAresta, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE)
                                    .add(btRemoverAresta, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE))
                                .add(6, 6, 6))
                            .add(layout.createSequentialGroup()
                                .add(lbNomeDoNo)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(tfNomeNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 124, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(lbCustoDoNo)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(tfCustoNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 47, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                .add(lbEstadoNo)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                .add(cbEstadoNo, 0, 160, Short.MAX_VALUE)))
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(lbNomeDoGrafo)
                            .add(tfNomeGrafo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                        .add(10, 10, 10))
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(btAbrir)
                            .add(btSalvar))
                        .add(18, 18, 18)))
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(layout.createSequentialGroup()
                        .add(btAdicionarGrafo)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btAlterarGrafo)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btRemoverGrafo)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btVisualizarNo))
                    .add(scrollPaneGrafo, 0, 0, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(separator1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(lbNomeDoNo)
                    .add(tfNomeNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(lbCustoDoNo)
                    .add(tfCustoNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(lbEstadoNo)
                    .add(cbEstadoNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(scrollPaneNo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 89, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(layout.createSequentialGroup()
                        .add(btAdicionarNo)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btAlterarNo)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btRemoverNo)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(separator2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(lbNomeDaAresta)
                    .add(tfNomeAresta, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(lbCustoAresta)
                    .add(tfCustoAresta, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(lbNoA)
                    .add(cbNoA, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(lbNoB)
                    .add(cbNoB, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(scrollPaneAresta, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 89, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(layout.createSequentialGroup()
                        .add(btAdicionarAresta)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btAlterarAresta)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btRemoverAresta)))
                .addContainerGap(20, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void atualizaItensGrafoTela(int selected) {
        if (selected >= 0) {
            listGrafo.setSelectedIndex(selected);
            tfNomeGrafo.setText(listGrafo.getSelectedValue().toString());
        }
    }

    // Adiciona um Grafo
    private void btAdicionarGrafoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAdicionarGrafoActionPerformed
        try {
            Grafo grafo = new Grafo(tfNomeGrafo.getText());
            controlador.addGrafo(grafo);
            modelGrafo.addElement(grafo.getNome());
            atualizaItensGrafoTela(modelGrafo.size() - 1);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btAdicionarGrafoActionPerformed

    private void btRemoverGrafoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btRemoverGrafoActionPerformed
        if (modelGrafo.size() > 0) {
            try {
                controlador.removeGrafo(listGrafo.getSelectedValue().toString());
                modelGrafo.remove(listGrafo.getSelectedIndex());
                atualizaItensGrafoTela(modelGrafo.size() - 1);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "Não existe um grafo selecionado para remoção", "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btRemoverGrafoActionPerformed

    private void btAlterarGrafoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAlterarGrafoActionPerformed
        if (modelGrafo.size() > 0) {
            int selected = listGrafo.getSelectedIndex();
            try {
                controlador.alteraNomeGrafo(modelGrafo.get(selected).toString(), tfNomeGrafo.getText());
                modelGrafo.remove(selected);
                modelGrafo.add(selected, tfNomeGrafo.getText());
                atualizaItensGrafoTela(selected);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "Não existe um grafo selecionado para alteração", "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btAlterarGrafoActionPerformed

    private void listGrafoValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listGrafoValueChanged
        atualizaListaNos();
    }//GEN-LAST:event_listGrafoValueChanged

    private void listGrafoMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_listGrafoMouseClicked
        int index;
        if ((index = listGrafo.getSelectedIndex()) != -1) {
            tfNomeGrafo.setText(modelGrafo.getElementAt(index).toString());
        }       
    }//GEN-LAST:event_listGrafoMouseClicked

    private void btAdicionarNoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAdicionarNoActionPerformed
        try {
            Grafo grafo = getGrafoSelecionado();
            No no = criaNoDaTela();
            grafo.addNo(no);
            atualizaJListNo(no);            
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btAdicionarNoActionPerformed

    private void listNoMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_listNoMouseClicked
        try {
            No no = getNoSelecionado();
            if (no != null) {
                tfNomeNo.setText(no.getNome());
                tfCustoNo.setText(String.valueOf(no.getCusto()));
                cbEstadoNo.setSelectedIndex(no.getEstado().getIndex());
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_listNoMouseClicked

    private void btRemoverNoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btRemoverNoActionPerformed
        if (modelNo.size() > 0) {
            try {
                No no = getNoSelecionado();
                Grafo grafo = getGrafoSelecionado();
                if (grafo != null) {
                    grafo.removeNo(no.getNome());
                    modelNo.remove(listNo.getSelectedIndex());
                    atualizaItensNoTela(modelNo.size() - 1);
                }
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "Não existe um Nó selecionado para remoção", "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btRemoverNoActionPerformed

    private No criaNoDaTela() throws Exception {
        //Cria o nó
        int index = cbEstadoNo.getSelectedIndex();
        NoEstado noEstado = (index == 0 ? NoEstado.INICIAL : (index == 1) ? NoEstado.INTERMEDIARIO : NoEstado.FINAL);
        try {
            No no = new No(tfNomeNo.getText(), Float.parseFloat(tfCustoNo.getText()), noEstado);
            return no;        
        } catch (NumberFormatException nfe) {
            throw new Exception("O custo do Nó não é um valor válido");
        }        
    }

    private void btAlterarNoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAlterarNoActionPerformed
        if (modelNo.size() > 0) {
            int selected = listNo.getSelectedIndex();
            try {
                No noAntigo = getNoSelecionado();
                No noNovo = criaNoDaTela();
                controlador.alteraNo(getGrafoSelecionado(), noAntigo, noNovo);
                modelNo.remove(selected);
                modelNo.add(selected, noNovo);
                atualizaItensNoTela(selected);
                atualizaListaArestas();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
    }//GEN-LAST:event_btAlterarNoActionPerformed

    private void atualizaListaNos() {
        try {
            modelNo.removeAllElements();
            Grafo grafo = getGrafoSelecionado();
            if (grafo != null) {
                LinkedHashMap listaNo = (LinkedHashMap) grafo.getListaNo();
                for (Iterator itNo = listaNo.keySet().iterator(); itNo.hasNext();) {
                    String keyNo = (String) itNo.next();
                    No no = (No) listaNo.get(keyNo);
                    atualizaJListNo(no);
                }
                atualizaListaArestas();
            }
        } catch (Exception ex) {
            Logger.getLogger(FrmInterface.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void atualizaListaArestas() {
        modelAresta.removeAllElements();
        LinkedHashMap listaArestas = new LinkedHashMap();
        try {
            //Obtém todas as arestas de todos os nós.
            Grafo grafo = getGrafoSelecionado();
            if (grafo != null) {
                LinkedHashMap listaNo = (LinkedHashMap) grafo.getListaNo();
                for (Iterator itNo = listaNo.keySet().iterator(); itNo.hasNext();) {
                    String keyNo = (String) itNo.next();
                    No no = (No) listaNo.get(keyNo);

                    LinkedHashMap listaAresta = (LinkedHashMap) no.getListaArestas();
                    for (Iterator itAresta = listaAresta.keySet().iterator(); itAresta.hasNext();) {
                        String keyAresta = (String) itAresta.next();
                        Aresta aresta = (Aresta) listaAresta.get(keyAresta);
                        listaArestas.put(aresta.getNome(), aresta);
                    }
                }

                //Adiciona as arestas na tela
                for (Iterator itAresta = listaArestas.keySet().iterator(); itAresta.hasNext();) {
                    String keyAresta = (String) itAresta.next();
                    Aresta aresta = (Aresta) listaArestas.get(keyAresta);
                    atualizaJListAresta(aresta);
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(FrmInterface.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void listNoValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listNoValueChanged
        atualizaComboBoxNos();
        atualizaCamposAresta();
    }//GEN-LAST:event_listNoValueChanged

    private void btAdicionarArestaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAdicionarArestaActionPerformed
        try {
             Aresta aresta = criaArestaDaTela();

            //Verifica se a aresta já existe na tela
            if (getGrafoSelecionado().getAresta(aresta.getNome()) != null) {
                throw new Exception("Aresta informada já existe no grafo");
            }

            //Adiciona a aresta nos nós
            No noEsquerda = aresta.getNoEsquerda();
            No noDireita = aresta.getNoDireita();
            noEsquerda.addAresta(aresta);
            noDireita.addAresta(aresta);
            //Atualização da tela
            atualizaJListAresta(aresta);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btAdicionarArestaActionPerformed

    private void listArestaMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_listArestaMouseClicked
        atualizaCamposAresta();
    }//GEN-LAST:event_listArestaMouseClicked

    private void btRemoverArestaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btRemoverArestaActionPerformed
        if (modelAresta.size() > 0) {
            try {
                Aresta aresta = getArestaSelecionada();
                //Remove a aresta nos nós
                No noEsquerda = aresta.getNoEsquerda();
                No noDireita = aresta.getNoDireita();
                noEsquerda.removeAresta(aresta.getNome());
                noDireita.removeAresta(aresta.getNome());
                modelAresta.remove(listAresta.getSelectedIndex());
                atualizaItensArestaTela(modelAresta.size() - 1);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
    }//GEN-LAST:event_btRemoverArestaActionPerformed

    private void btAlterarArestaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAlterarArestaActionPerformed
        if (modelAresta.size() > 0) {
            int selected = listAresta.getSelectedIndex();
            try {
                Aresta arestaAntiga = getArestaSelecionada();
                Aresta arestaNova = criaArestaDaTela();
                controlador.alteraAresta(getGrafoSelecionado(), arestaAntiga, arestaNova);
                modelAresta.remove(selected);
                modelAresta.add(selected, arestaNova);
                atualizaItensArestaTela(selected);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
    }//GEN-LAST:event_btAlterarArestaActionPerformed

    private void btSalvarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btSalvarActionPerformed
        salvaGrafos();
    }//GEN-LAST:event_btSalvarActionPerformed

    private void btAbrirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAbrirActionPerformed
        carregaGrafos();
    }//GEN-LAST:event_btAbrirActionPerformed

    private void btVisualizarNoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btVisualizarNoActionPerformed
        if (listGrafo.getSelectedIndex() != -1) {
            try {
                Grafo grafo = controlador.getGrafo((String) listGrafo.getSelectedValue());
                FrmResultado.getInstance().showResultado(grafo);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "Não existe um grafo selecionado para visualização", "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btVisualizarNoActionPerformed

    private void atualizaCamposAresta() {
        try {
            Aresta aresta = getArestaSelecionada();
            if (aresta != null) {
                tfNomeAresta.setText(aresta.getNome());
                tfCustoAresta.setText(String.valueOf(aresta.getCusto()));
                modelCbNoA.setSelectedItem(aresta.getNoEsquerda().getNome());
                modelCbNoB.setSelectedItem(aresta.getNoDireita().getNome());
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void atualizaJListAresta(Aresta aresta) {
        modelAresta.addElement(aresta);
        atualizaItensArestaTela(modelAresta.size() - 1);

    }

    private void atualizaItensArestaTela(int selected) {
        if (selected >= 0) {
            listAresta.setSelectedIndex(selected);
            Aresta aresta = getArestaSelecionada();
            tfNomeAresta.setText(aresta.getNome());
            tfCustoAresta.setText(String.valueOf(aresta.getCusto()));
            modelCbNoA.setSelectedItem(aresta.getNoEsquerda().getNome());
            modelCbNoB.setSelectedItem(aresta.getNoDireita().getNome());
        }
    }

    private Aresta getArestaSelecionada() {
        Aresta aresta = (Aresta) listAresta.getSelectedValue();
        return aresta;
    }

    private Aresta criaArestaDaTela() throws Exception {
        Grafo grafo = getGrafoSelecionado();
        No noEsquerda = grafo.getNo(modelCbNoA.getSelectedItem().toString());
        No noDireita = grafo.getNo(modelCbNoB.getSelectedItem().toString());
        try {
            return new Aresta(tfNomeAresta.getText(), Float.parseFloat(tfCustoAresta.getText()), noDireita, noEsquerda);
        }catch (NumberFormatException nfe) {
            throw new Exception("O custo da aresta não é um valor válido");
        }
    }

    private void atualizaComboBoxNos() {
        try {
            modelCbNoA.removeAllElements();
            modelCbNoB.removeAllElements();
            LinkedHashMap listaNo = (LinkedHashMap) getGrafoSelecionado().getListaNo();

            for (Iterator it = listaNo.keySet().iterator(); it.hasNext();) {
                String key = (String) it.next();
                No no = (No) listaNo.get(key);
                modelCbNoA.addElement(no.getNome());
                modelCbNoB.addElement(no.getNome());
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void atualizaJListNo(No no) {
        modelNo.addElement(no);
        atualizaItensNoTela(modelNo.size() - 1);
    }

    private void atualizaItensNoTela(int selected) {
        if (selected >= 0) {
            listNo.setSelectedIndex(selected);
            No no = getNoSelecionado();
            tfNomeNo.setText(no.getNome());
            tfCustoNo.setText(String.valueOf(no.getCusto()));
            cbEstadoNo.setSelectedIndex(no.getEstado().getIndex());
        }
    }

    private No getNoSelecionado() {
        No no = (No) listNo.getSelectedValue();
        return no;
    }

    private Grafo getGrafoSelecionado() throws Exception {
        if (listGrafo.getSelectedValue() != null) {
            return controlador.getGrafo(listGrafo.getSelectedValue().toString());
        }
        throw new Exception("Não existe um grafo selecionado");
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new FrmInterface().setVisible(true);
            }
        });
    }

    private void salvaGrafos() {
        JFileChooser fileopen = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Arquivo de Grafos", "gra");
        fileopen.addChoosableFileFilter(filter);
        int ret = fileopen.showDialog(null, "Salvar");

        if (ret == JFileChooser.APPROVE_OPTION) {
            try {
                FileOutputStream fos = new FileOutputStream(fileopen.getSelectedFile().getCanonicalPath() + ".gra");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(controlador.getListaGrafos());
                oos.close();
                fos.close();
            } catch (Exception e) {
                JOptionPane.showMessageDialog(this, "Erro salvando o arquivo de grafos", "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private void refreshUi() {
        modelGrafo.clear();
        modelNo.clear();
        modelAresta.clear();
        modelCbNoA.removeAllElements();
        modelCbNoB.removeAllElements();

        HashMap<String, Grafo> map = controlador.getListaGrafos();
        Collection<Grafo> grafos = map.values();
        for (Grafo grafo: grafos) {
            modelGrafo.addElement(grafo.getNome());
            Collection<No> nos = grafo.getListaNo().values();
            for (No no: nos) {
                modelNo.addElement(no);
                modelCbNoA.addElement(no.getNome());
                modelCbNoB.addElement(no.getNome());
                Collection<Aresta> arestas = no.getListaArestas().values();
                for (Aresta aresta: arestas) {
                    modelAresta.addElement(aresta);
                }
            }
        }        
    }

    private void carregaGrafos() {
        JFileChooser fileopen = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Arquivo de Grafos", "gra");
        fileopen.addChoosableFileFilter(filter);
        int ret = fileopen.showDialog(null, "Abrir arquivo");

        if (ret == JFileChooser.APPROVE_OPTION) {
            try {
                FileInputStream fis = new FileInputStream(fileopen.getSelectedFile().getCanonicalPath());
                ObjectInputStream ois = new ObjectInputStream(fis);
                HashMap<String, Grafo> map = (HashMap<String, Grafo>) ois.readObject();
                controlador.setListaGrafos(map);
                refreshUi();
                ois.close();
                fis.close();
            } catch (Exception e) {
                JOptionPane.showMessageDialog(this, e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
                JOptionPane.showMessageDialog(this, "Não foi possível abrir o arquivo selecionado", "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btAbrir;
    private javax.swing.JButton btAdicionarAresta;
    private javax.swing.JButton btAdicionarGrafo;
    private javax.swing.JButton btAdicionarNo;
    private javax.swing.JButton btAlterarAresta;
    private javax.swing.JButton btAlterarGrafo;
    private javax.swing.JButton btAlterarNo;
    private javax.swing.JButton btRemoverAresta;
    private javax.swing.JButton btRemoverGrafo;
    private javax.swing.JButton btRemoverNo;
    private javax.swing.JButton btSalvar;
    private javax.swing.JButton btVisualizarNo;
    private javax.swing.JComboBox cbEstadoNo;
    private javax.swing.JComboBox cbNoA;
    private javax.swing.JComboBox cbNoB;
    private javax.swing.JLabel lbCustoAresta;
    private javax.swing.JLabel lbCustoDoNo;
    private javax.swing.JLabel lbEstadoNo;
    private javax.swing.JLabel lbNoA;
    private javax.swing.JLabel lbNoB;
    private javax.swing.JLabel lbNomeDaAresta;
    private javax.swing.JLabel lbNomeDoGrafo;
    private javax.swing.JLabel lbNomeDoNo;
    private javax.swing.JList listAresta;
    private javax.swing.JList listGrafo;
    private javax.swing.JList listNo;
    private javax.swing.JScrollPane scrollPaneAresta;
    private javax.swing.JScrollPane scrollPaneGrafo;
    private javax.swing.JScrollPane scrollPaneNo;
    private javax.swing.JSeparator separator1;
    private javax.swing.JSeparator separator2;
    private javax.swing.JTextField tfCustoAresta;
    private javax.swing.JTextField tfCustoNo;
    private javax.swing.JTextField tfNomeAresta;
    private javax.swing.JTextField tfNomeGrafo;
    private javax.swing.JTextField tfNomeNo;
    // End of variables declaration//GEN-END:variables
}
